module GTranslate
  class Client
    @@translate_url     = 'http://google.com/translate_t'

    @@result_dom_id     = :result_box
    
    @@result_regex      = /<div[^>]*id=#{@@result_dom_id}[^>]*>(([^<]|<br>|<br ?\/>)*)/u
    
    @@translation_pairs = {
      'ar' => ['en'],
      'zh' => ['en'],
      'nl' => ['en'],
      'en' => ['ar', 'zh', 'nl', 'fr', 'de', 'el', 'it', 'ja', 'ko', 
               'pt', 'ru', 'es'],
      'fr' => ['en', 'de'],
      'de' => ['en', 'fr'],
      'el' => ['en'],
      'it' => ['en'],
      'ja' => ['en'],
      'ko' => ['en'],
      'pt' => ['en'],
      'ru' => ['en'],
      'es' => ['en']
    } 
    
    # Execute request for google translate
    # 
    # ==== Parameters
    #   opts<Hash>:: An options hash (see below)
    # 
    # ==== Options (opts)
    # :text<String>:: The source text you want translated
    # :source<String>:: Source language in iso_639_2 format
    # :target<String>:: Target language in iso_639_2 format
    #
    # ==== Returns
    # String:: The translated text
    #—
    # @public
    def request( opts = {} )
      return '' unless translatable?( opts[:source], opts[:target] )
      
      the_language_pair, and_text = 
        language_pair_for( opts[:source], opts[:target] ), opts[:text]

      the_response = get_response_given( the_language_pair, and_text )

      return extracted_result_from( the_response )
    end
    
    protected 
      def translatable?( source, target )
        @@translation_pairs[source] && @@translation_pairs[source].include?( target )
      end
      
      def get_response_given( language_pair, text )
        require 'net/http'
        require 'uri'

        uri     = URI.parse(@@translate_url)
        http    = Net::HTTP.new(uri.host, uri.port)
        params  = { :langpair => language_pair, :text => text, :hl => 'en', :ie => 'UTF8', :oe => 'UTF8' }
        data    = params.collect { |k, v| "#{k}=#{ URI.escape(v)}" }.join('&')
        resp    = http.post(uri.path, data)
        resp.body
      end
      
      def language_pair_for( source, target )
        "#{source}|#{target}".downcase
      end
      
      def extracted_result_from( string )
        matches = string.match( @@result_regex )
        CGI.unescapeHTML( scrub( matches && matches[1] ) )
      end
      
      def scrub( string )
        string.split(/<br>|<br ?\/>/).collect { |chunk| chunk.strip }.join( "\n" )
      end
  end
end